# -*- coding: utf-8 -*-
# !/usr/bin/env python

from fortranformat import FortranRecordReader
import numpy as np
import uuid
from datetime import datetime, timedelta
import time
from metlib.shell.fileutil import *
from littler.models import *
from django.conf import settings
from django.core import serializers
from metlib.shell.fileutil import BASENAME, DIRNAME, CP, RM
from littler.map_data_models import *
import json
import threading, Queue
from multiprocessing import cpu_count

# 类库设计
class MapPointData(object):
    # 表示一个区域内点数据合集的类，树型集合变量,
    def __init__(self, round_frist_lat, round_frist_lon):
        self.point_info = self.set_map_point_info(round_frist_lat, round_frist_lon)

    # 生成单个层级坐标内点数据坐标
    def set_map_point_info(self, round_frist_lat, round_frist_lon):
        pass

    # 根据聚合点坐标获取点的组
    @staticmethod
    def get_round_frist():
        lprs = LittlerPointRoundMinus1.objects.raw(
            "select cast(latitude as text)|| cast(longitude as text) as id,latitude,longitude from littler_point_round_minus1")
        return serializers.serialize("json", lprs)
    # 更具一级获取获取原始坐标组
    @staticmethod
    def get_frist_original(round_frist_lat, round_frist_lon):
        lprs = LittlePoint.objects.raw(
            "select * from littler_littlepoint where round((latitude)::numeric, (-1))=%s and round((longitude)::numeric, (-1))=%s" % (
            round_frist_lat, round_frist_lon))
        return serializers.serialize("json", lprs)

    # 根据坐标首位获取坐标点
    @staticmethod
    def get_original(frist_lat, frist_lon, end_lat, end_lon):
        lprs = LittlePoint.objects.raw(
            "select * from littler_littlepoint where latitude>%s and longitude>%s and latitude<%s and longitude<%s " % (
                frist_lat, frist_lon, end_lat, end_lon))
        return serializers.serialize("json", lprs)

    # 根据一级获取两级
    @staticmethod
    def get_round_sec(round_frist_lat, round_frist_lon):
        lprs = LittlerPointRoundMinus025.objects.raw(
            "select cast(latitude as text)|| cast(longitude as text) as id,latitude,longitude from littler_point_round_minus025  where round((latitude)::numeric, (-1))=%s and round((longitude)::numeric, (-1))=%s" % (
                round_frist_lat, round_frist_lon))
        return serializers.serialize("json", lprs)

    # 根据二级坐标获取获取原始坐标组
    @staticmethod
    def get_sec_original(round_sec_lat, round_sec_lon):
        lprs = LittlePoint.objects.raw(
            "select * from littler_littlepoint where (round((littler_littlepoint.latitude / (5)::double precision)) * (5)::double precision)=%s and (round((littler_littlepoint.longitude / (5)::double precision)) * (5)::double precision)=%s" % (
            round_sec_lat, round_sec_lon))
        return serializers.serialize("json", lprs)

    # 根据二级坐标获取三级
    @staticmethod
    def get_round_thrid(round_sec_lat, round_sec_lon):
        lprs = LittlerPointRound.objects.raw(
            "select cast(latitude as text)|| cast(longitude as text) as id,latitude,longitude from littler_point_round  where  (round((latitude / (5)::double precision)) * (5)::double precision)=%s and (round((longitude / (5)::double precision)) * (5)::double precision)=%s" % (
                round_sec_lat, round_sec_lon))
        return serializers.serialize("json", lprs)

    # 根据三级坐标获取原始坐标组
    @staticmethod
    def get_thrid_original(round_thrid_lat, round_thrid_lon):
        lprs = LittlePoint.objects.raw(
            "select * from littler_littlepoint where round(littler_littlepoint.latitude)=%s and round(littler_littlepoint.longitude)=%s" % (
            round_thrid_lat, round_thrid_lon))
        return serializers.serialize("json", lprs)

    # 根据区域坐标返回获取原始坐标组
    @staticmethod
    def get_for_range(start_lat_lon, end_lat_lon):
        start_lat, start_lon = start_lat_lon.split("_")
        end_lat, endlon = end_lat_lon.split("_")
        lprs = LittlePoint.objects.raw(
            "select * from littler_littlepoint where latitude BETWEEN %s and %s and longitude between %s and %s" % (
                start_lat, end_lat, start_lon, endlon))
        return serializers.serialize("json", lprs)

    # 获取坐标点对应详细信息
    @staticmethod
    def get_original_data(lat, lon):
        lprs = LittlePoint.objects.raw(
            "select * from littler_littlepoint where latitude=%s and longitude=%s" % (lat, lon))
        return serializers.serialize("json", lprs)

    # 获取坐标点对应详细信息
    @staticmethod
    def get_china_original_data(platform=None):
        sql = "select * from littler_littlepoint_china"
        if platform is not None:
            sql = "select * from littler_littlepoint_china where platform=%s " % (platform)
        lprs = LittlePoint.objects.raw(sql)
        return serializers.serialize("json", lprs)

    # 获取坐标点对应详细信息
    @staticmethod
    def get_china_station_data(platform=None):
        sql = "select * from littler_littlepoint_china_data"
        if platform is not None:
            sql = "select * from littler_littlepoint_china_data where platform='%s' " % (platform)
        lprs = LittlePoint.objects.raw(sql)
        return lprs


LittleDataList = {}
class myThread(threading.Thread):
    def __init__(self, sqlstr, workQueue):
        threading.Thread.__init__(self)
        self.sqlstr = sqlstr
        self.workQueue = workQueue

    def run(self):
        ld = LittleData.objects.raw(self.sqlstr)
        lds = []
        for l in ld:
            lds.append(l)
        point_id = str(uuid.uuid1())
        LittleDataList[point_id] = lds
        self.workQueue.put(point_id)


class MapLitterData(object):
    # 获取点数据
    # datetime_division
    @staticmethod
    def get_point_for_id(id, begdate, enddate):

        ld = LittleData.objects.raw(
            "select * from littler_littledata where little_point_id='%s' and date_char between '%s' and '%s' order by date_char ASC " % (
                id, begdate, enddate))

        return ld

    # 获取点数据
    # datetime_division
    @staticmethod
    def get_point_for_stationid(station_id, begdate, enddate):

        sql = "select * from littler_littlepoint_china where station_id='%s' " % (station_id)
        lprs = LittlePoint.objects.raw(sql)
        lds = [];
        for lp in lprs:
            begdate_tmp = datetime.strptime(begdate, "%Y-%m-%d %H:%M:%S").replace(tzinfo=None)
            enddate_tmp = datetime.strptime(enddate, "%Y-%m-%d %H:%M:%S").replace(tzinfo=None)
            frist_data_time = lp.frist_data_time.replace(tzinfo=None)
            last_data_time = lp.last_data_time.replace(tzinfo=None)
            if frist_data_time > begdate_tmp:
                begdate_tmp = frist_data_time
            if last_data_time < enddate_tmp:
                enddate_tmp = last_data_time
            if (enddate_tmp - begdate_tmp).days > 90:
                lds = lds + MapLitterData.get_point_pt_data_chnn(lp.point_id, begdate_tmp.strftime("%Y-%m-%d %H:%M:%S"),
                                                                 enddate_tmp.strftime("%Y-%m-%d %H:%M:%S"))
            else:
                lds = lds + MapLitterData.get_point_pt_data_normal(lp.point_id,
                                                                   begdate_tmp.strftime("%Y-%m-%d %H:%M:%S"),
                                                                   enddate_tmp.strftime("%Y-%m-%d %H:%M:%S"))
        if len(lds) != 0:
            lds = sorted(lds, key=lambda d: d.date_char)
        return lds

    # 获取点数据
    # datetime_division
    @staticmethod
    def get_point_pt_data(lat, lon, begdate, enddate):
        lprs = LittlePoint.objects.raw(
            "select * from littler_littlepoint "
            "where latitude=%s and longitude= %s" % (lat, lon))
        if len(list(lprs)) > 0:
            point_id = lprs[0].point_id
            ld = LittleData.objects.raw(
                "select * from littler_littledata where little_point_id='%s' and date_char between '%s' and '%s' order by date_char ASC " % (
                    point_id, begdate, enddate))
        else:
            ld = []
        return ld
    # datetime_division
    @staticmethod
    def get_point_pt_data_chnn(point_id, begdate, enddate):
        tsk = []
        workQueue = Queue.Queue()
        datetime_list = datetime_division(datetime.strptime(begdate, "%Y-%m-%d %H:%M:%S"),
                                          datetime.strptime(enddate, "%Y-%m-%d %H:%M:%S"), cpu_count())
        for k, begdate in enumerate(datetime_list):
            if k == len(datetime_list) - 1:
                break;
            enddate = datetime_list[k + 1]

            sqlstr = "select * from littler_littledata where little_point_id='%s' and date_char between '%s' and '%s' order by date_char ASC " % (
                point_id, time.strftime("%Y-%m-%d %H:%M:%S", begdate), time.strftime("%Y-%m-%d %H:%M:%S", enddate))
            mthread = myThread(sqlstr, workQueue)
            mthread.start()
            tsk.append(mthread)
        for tt in tsk:
            tt.join()
        ld = []
        while not workQueue.empty():
            point_id_tmp = workQueue.get()
            ld = ld + LittleDataList[point_id_tmp]
            # LittleDataList.pop(point_id_tmp)
        return ld

    # 获取点数据
    # datetime_division
    @staticmethod
    def get_point_pt_data_normal(point_id, begdate, enddate):
        ld = LittleData.objects.raw(
            "select * from littler_littledata where little_point_id='%s' and date_char between '%s' and '%s' order by date_char ASC " % (
                point_id, begdate, enddate))
        lds = []
        for l in ld:
            lds.append(l)
        return lds
    # # 获取点数据,按照年风阻
    # @staticmethod
    # def get_point_py_data(lat, lon, begdate, enddate):
    #     lprs = LittlePoint.objects.raw(
    #         "select * from littler_littlepoint where latitude=%s and longitude= %s" % (lat, lon))
    #     if len(lprs) > 0:
    #         ld = LittleData.objects.filter(little_point_id=lprs[0].point_id, date_char__gt=begdate,
    #                                        date_char__lt=enddate)
    #     else:
    #         ld = "[]"
    #     return serializers.serialize("json", ld)
    # # 获取点数据,按照年风阻
    # @staticmethod
    # def get_point_pm_data(lat, lon, begdate, enddate):
    #     lprs = LittlePoint.objects.raw(
    #         "select * from littler_littlepoint where latitude=%s and longitude= %s" % (lat, lon))
    #     if len(lprs) > 0:
    #         ld = LittleData.objects.filter(little_point_id=lprs[0].point_id, date_char__gt=begdate,
    #                                        date_char__lt=enddate)
    #     else:
    #         ld = "[]"
    #     return serializers.serialize("json", ld)
    #
    # # 获取点数据,按照年风阻
    # @staticmethod
    # def get_point_pd_data(lat, lon, begdate, enddate):
    #     lprs = LittlePoint.objects.raw(
    #         "select * from littler_littlepoint where latitude=%s and longitude= %s" % (lat, lon))
    #     if len(lprs) > 0:
    #         ld = LittleData.objects.filter(little_point_id=lprs[0].point_id, date_char__gt=begdate,
    #                                        date_char__lt=enddate)
    #     else:
    #         ld = "[]"
    #     return serializers.serialize("json", ld)

    # 获取区域数据
    @staticmethod
    def get_area_data(start_lat_lon, end_lat_lon, begdate, enddate):
        start_lat, start_lon = start_lat_lon.split("_")
        end_lat, endlon = end_lat_lon.split("_")
        lprs = LittlePoint.objects.raw(
            "select * from littler_littlepoint where latitude BETWEEN %s and %s and longitude between %s and %s" % (
            start_lat, end_lat, start_lon, endlon))

        pass


def timestamp_datetime(value, format=None):
    if format is None:
        format = '%Y-%m-%d %H:%M:%S'
    # value为传入的值为时间戳(整形)，如：1332888820
    value = time.localtime(value)
    ## 经过localtime转换后变成
    ## time.struct_time(tm_year=2012, tm_mon=3, tm_mday=28, tm_hour=6, tm_min=53, tm_sec=40, tm_wday=2, tm_yday=88, tm_isdst=0)
    # 最后再经过strftime函数转换为正常日期格式。
    dt = time.strftime(format, value)
    return dt


def datetime_timestamp(dt):
    # dt为字符串
    # 中间过程，一般都需要将字符串转化为时间数组
    time.strptime(dt, '%Y-%m-%d %H:%M:%S')
    ## time.struct_time(tm_year=2012, tm_mon=3, tm_mday=28, tm_hour=6, tm_min=53, tm_sec=40, tm_wday=2, tm_yday=88, tm_isdst=-1)
    # 将"2012-03-28 06:53:40"转化为时间戳
    s = time.mktime(time.strptime(dt, '%Y-%m-%d %H:%M:%S'))
    return int(s)


def datetime_timestamp_dt(dt):
    # dt为字符串
    # 中间过程，一般都需要将字符串转化为时间数组
    # time.strptime(dt, '%Y-%m-%d %H:%M:%S')
    ## time.struct_time(tm_year=2012, tm_mon=3, tm_mday=28, tm_hour=6, tm_min=53, tm_sec=40, tm_wday=2, tm_yday=88, tm_isdst=-1)
    # 将"2012-03-28 06:53:40"转化为时间戳
    dt_str = datetime.strftime(dt, '%Y-%m-%d %H:%M:%S')
    s = time.mktime(time.strptime(dt_str, '%Y-%m-%d %H:%M:%S'))
    return int(s)


def datetime_division(start_time, end_time, count):
    start_time_stamp = datetime_timestamp_dt(start_time)
    end_time_stamp = datetime_timestamp_dt(end_time)
    time_length = (end_time_stamp - start_time_stamp) / count
    datetime_array = []
    while start_time_stamp < end_time_stamp:
        datetime_array.append(time.localtime(start_time_stamp))
        start_time_stamp = start_time_stamp + time_length
    datetime_array.append(time.localtime(end_time_stamp))
    return datetime_array
